#ifndef BYTE_VIEW_H
#define BYTE_VIEW_H

#include <QAbstractScrollArea>
#include <QFont>
#include <QVector>
#include <QMenu>
#include <QSize>
#include <QString>
#include <QTextLayout>
#include <QVector>
#include "utils.h"
#include "utils/buffer.h"

typedef enum {
    BYTES_HEX,
    BYTES_BITS
} bytes_view_type;

#define UTF8_MIDDLE_DOT                     "\xc2\xb7"      /*   183 /   0xb7 */

class BufferView : public QAbstractScrollArea
{
    Q_OBJECT

public:
    explicit BufferView(FERange range, QWidget *parent = 0);
    ~BufferView();

    virtual QSize minimumSizeHint() const;

    void setFormat(bytes_view_type format);
    bool isEmpty() const;

signals:
    void byteViewSettingsChanged();

public slots:
    void setMonospaceFont(const QFont &mono_font);
    void updateByteViewSettings();

    void markRange(FERange range);

protected:
    virtual void paintEvent(QPaintEvent *);
//    virtual void resizeEvent(QResizeEvent *);
    virtual void contextMenuEvent(QContextMenuEvent *event);

private:
    // Text highlight modes.
    typedef enum {
        ModeNormal,
        ModeField,
        ModeProtocol,
        ModeOffsetNormal,
        ModeOffsetField,
        ModeNonPrintable
    } HighlightMode;

    QTextLayout *layout_;
    FERange range_;

    void updateLayoutMetrics();
    int stringWidth(const QString &line);
    void drawLine(QPainter *painter, const int offset, const int row_y);
    bool addFormatRange(QList<QTextLayout::FormatRange> &fmt_list, int start, int length, HighlightMode mode);
    bool addHexFormatRange(QList<QTextLayout::FormatRange> &fmt_list, uint64_t mark_bit_start, uint64_t mark_bit_length, int tvb_offset, int max_tvb_pos, HighlightMode mode);
    bool addAsciiFormatRange(QList<QTextLayout::FormatRange> &fmt_list, uint64_t mark_bit_start, uint64_t mark_bit_length, int tvb_offset, int max_tvb_pos, HighlightMode mode);
    void scrollToByte(int byte);
    void updateScrollbars();

    void createContextMenu();
    void updateContextMenu();

    int offsetChars(bool include_pad = true);
    int offsetPixels();
    int hexPixels();
    int asciiPixels();
    int totalPixels();

    QRgb alphaBlend(const QColor &color1, const QColor &color2, qreal alpha);
    int hexChars();

    static const int separator_interval_;

    bytes_view_type gui_bytes_view_;

    // Colors
    QColor offset_normal_fg_;
    QColor offset_field_fg_;

    // Data
    QMenu ctx_menu_;

    bool show_offset_;          // Should we show the byte offset?
    bool show_hex_;             // Should we show the hex display?
    int row_width_;             // Number of bytes per line
    int font_width_;            // Single character width and text margin. NOTE: Use fontMetrics::width for multiple characters.
    int line_height_;           // Font line spacing

    // Context menu actions
    QAction *action_bytes_hex_;
    QAction *action_bytes_bits_;

private slots:
    void setHexDisplayFormat(QAction *action);
};

#endif // BYTE_VIEW_H
